class TextField
{
  String contents;
  String usrEntry, displayedText;
  color theColor;
  int x, y;
  boolean isSelected;
  int letterSelected;
  int firstCharShowing;
  int indexOfSelectedCity;
  float[] theCoords;
  private PFont cityFont;
  private int T_WIDTH = 140;
  private int T_HEIGHT = 20;
  private String FILENAME = "CityData.csv";
  private String DEFAULT_TEXT = "Enter a city";
  private CityTable myCityTable;
  private int[] searchResults;
  private boolean isDropped;

  //constructor
  TextField( int r, int g, int b, int x, int y)
  {
    theColor = color( r, g, b);
    this.x = x;
    this.y = y;
    isSelected = false;
    isDropped = false;
    letterSelected = 0;
    firstCharShowing = 0;
    indexOfSelectedCity = -1;
    cityFont = createFont("Helvetica", 12);
    displayedText = usrEntry = DEFAULT_TEXT;
    myCityTable = new CityTable(FILENAME);
    theCoords = new float[2];
    searchResults = new int[0];
  }
  
  //The draw function for the textfield
  public void render()
  {
    rectMode (CORNER);
    fill(255,255,255);
    text("City Search", x,y,T_WIDTH, T_HEIGHT);
    fill( theColor, 100);
    stroke( theColor, 255);
    strokeWeight(2);
    rect( x, y+T_HEIGHT+10, T_WIDTH, T_HEIGHT);
    fill(255);
    textSize(12);
    textAlign(LEFT, TOP);
    text( displayedText, x + 3, y+T_HEIGHT+10 + 3);
    if( (searchResults != null) && (searchResults.length > 0) )
    {
      fill( theColor, 100);
      noStroke();
      rect( x, y + T_HEIGHT*2+10+1, T_WIDTH, ( (16 * searchResults.length) + 4) );fill(255);
      textSize(12);
      textAlign(LEFT, TOP);
      for( int i = 0; i < searchResults.length; i++)
      {
        int adjustedY = y + T_HEIGHT*2+10 + 3 + (16 * i);
        text( myCityTable.getCityName(searchResults[i]), x + 3, adjustedY);
      }
    }
  }
  
  //there should be a corresponding keyTyped() somewhere in the program that
  //calls this function and passes it the key that had been typed
  public void textHandler(char letter)
  {
    if( isSelected)
    {
      switch( letter)
      {
        case ENTER:
        case RETURN:
          contents = usrEntry;
          usrEntry = DEFAULT_TEXT;
          isDropped = false;
          //println(contents);
          //grab the coordinates of the selected city if it exists
          //put 90.0, 190.0 for the coordinates as they are imposible values
          indexOfSelectedCity = myCityTable.getCityIndex( contents);
          if( indexOfSelectedCity >= 0)
          {
            theCoords = myCityTable.getCoords( indexOfSelectedCity);
          }
          else
          {
            theCoords[0] = 100.0;
            theCoords[1] = 190.0;
          }
          //println( theCoords[0] + ", " + theCoords[1]);
          findMatches();
          break;
        case BACKSPACE:
          if( usrEntry.length() > 1 && (!usrEntry.equals(DEFAULT_TEXT)))
          {
            usrEntry = usrEntry.substring( 0, usrEntry.length() - 1);
          }
          else
          {
            usrEntry = DEFAULT_TEXT;
            isDropped = false;
          }
          if( firstCharShowing > 0)
          {
            firstCharShowing--;
          }
          findMatches();
          break;
        default:
          if( usrEntry.equals(DEFAULT_TEXT))
          {
            usrEntry = "" + letter;
          }
          else
          {
            usrEntry = usrEntry + letter;
            if( usrEntry.length() > 12)
            {
              firstCharShowing++;
            }
          }
          isDropped = true;
          findMatches();
          break;
      }
      setDisplayText();
    }
  }
  
  //handles mouse interaction
  public void mouseButtonHandler(int mX, int mY)
  {
    if( (mX > x) && ( mX < ( x + T_WIDTH ) ) && (mY > y+T_HEIGHT+10) && ( mY < ( y + T_HEIGHT*2+10 ) ) )
    {
      isSelected = true;
    }
    else if( (mX > x) && (mX < x + T_WIDTH)&& (mY>y + T_HEIGHT*2+10)&&(mY<y+250) )//you click on the list
    {
      for( int i = 0; i < searchResults.length; i++)
      {
        if( (mY < (y + T_HEIGHT*2+10 + 19 + (16 * i))) && ( mY > (y + T_HEIGHT*2+10 + 3 + (16 * i))) )
        {
          usrEntry = myCityTable.getCityName( searchResults[i]);
          setDisplayText();
        }
      }
    }
    else
    {
      isSelected = false;
    }
  }
  
  //makes the textFeild lose focus
  public void unselect()
  {
    isSelected = false;
  }
  
  public boolean isDropped()
  {
    return isDropped;
  }
  
  //returns the coordinates of the city chosen
  public float[] getCoordinates()
  {
    float[] temp = theCoords;
    theCoords = new float[2];
    theCoords[0] = 100.0;
    theCoords[1] = 190.0;
    return temp;
  }
  
  //finds the cities that might match what has been typed
  private void findMatches()
  {
    String[] theCities = myCityTable.getCityNames();
    String tempStr;
    searchResults = new int[200];
    int nResults = 0;
    for( int i = 0; i < theCities.length; i++)
    {
      if( theCities[i].length() >= usrEntry.length())
      {
        tempStr = theCities[i].substring(0, usrEntry.length());
        if( ( tempStr.toLowerCase() ).equals( usrEntry.toLowerCase() ) )
        {
          searchResults[nResults] = i;
          nResults++;
        }
      }
    }
    searchResults = subset(searchResults, 0, nResults);
  }
  
  //used to update or set the text to be displayed in the text field
  private void setDisplayText()
  {
    if( usrEntry.length() > 12)
    {
      displayedText = usrEntry.substring(firstCharShowing, (firstCharShowing + 12) );
    }
    else
    {
      displayedText = usrEntry;
    }
  }
  
  //checks to see if the text field is blocking the provided coordinates
  public boolean isBlocking( int objX, int objY)
  {
    if( ( y + T_HEIGHT * 2 + 29 + (16 * ( searchResults.length - 1))) > objY)
    {
      return true;
    }
    else
    {
      return false;
    }
  }
}

